package com.linking.third.party.manager;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.borealis.common.utils.DataUtils;
import com.google.common.collect.Maps;
import com.linking.third.party.pojo.bo.KuaiKanPayBO;
import com.linking.third.party.pojo.bo.KuaiKanPayResBO;
import com.linking.third.party.pojo.bo.KuaiKanPayVerifyBO;
import com.linking.third.party.pojo.bo.ReceiptVerifyBO;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

/**
 * @Author YaoWeiXin
 * @Date 2020/11/4 17:16
 * @Description 快看支付 管理类
 */
@Slf4j
public class KuaiKanManager {

  private final static String PROD_TRADE_URL = "https://api.kkmh.com";

  /**
   * 创建支付
   *
   * @param kuaiKanPayBO 快看支付参数
   * @return 创建结果
   */
  public static KuaiKanPayResBO doPay(KuaiKanPayBO kuaiKanPayBO) {
    boolean sendBox = kuaiKanPayBO.getSendBox();
    String appId = kuaiKanPayBO.getAppId();
    int waresId = 1;
    String orderId = kuaiKanPayBO.getOrderId();
    String notifyUrl = kuaiKanPayBO.getNotifyUrl();
    String openid = kuaiKanPayBO.getOpenid();
    String productDesc = kuaiKanPayBO.getProductDesc();
    BigDecimal amount = kuaiKanPayBO.getAmount();

    Map<String, Object> params = Maps.newHashMap();
    params.put("app_id", appId);
    params.put("wares_id", waresId);
    params.put("out_order_id", orderId);
    params.put("out_notify_url", notifyUrl);
    params.put("open_uid", openid);
    params.put("trans_money", amount);
    params.put("wares_name", productDesc);

    String sign = signKeyValue(params, kuaiKanPayBO.getAppSecret(), sendBox);
    if (sendBox) {
      log.debug("params====================={}", JSON.toJSONString(params));
      log.debug("sig params====================={}", sign);
    }
    return KuaiKanPayResBO.of(orderId, JSON.toJSONString(params), sign);
  }

  /**
   * 票据验证
   *
   * @param kuaiKanPayVerifyBO 快看票据验证参数
   * @return 票据验证结果
   */
  public static ReceiptVerifyBO receiptVerify(KuaiKanPayVerifyBO kuaiKanPayVerifyBO) {
    boolean sendBox = kuaiKanPayVerifyBO.getSendBox();
    // 1、组合参数
    String url = PROD_TRADE_URL + "/v2/game_pay/query_order";
    Map<String, Object> params = Maps.newHashMap();
    params.put("trans_data", kuaiKanPayVerifyBO.getTransData());
    params.put("sign", kuaiKanPayVerifyBO.getSign());
    if (sendBox) {
      log.debug("kuai kan receiptVerify=params===================={},{}", url, JSON.toJSONString(params));
    }
    // 2、请求校验
    String response = HttpUtil.post(url, params, 5000);
    if (sendBox) {
      log.debug("kuai kan receiptVerify=response===================={}", response);
    }
    if (StrUtil.isEmpty(response)) {
      return ReceiptVerifyBO.ofFail();
    }
    // 3、判断支付状态
    JSONObject data = JSON.parseObject(response);
    int ok = 200;
    int payOk = 2;
    String returnCode = "code";
    String payResult = "pay_status";
    if (ok != data.getInteger(returnCode)) {
      log.debug("kuai kan receiptVerify fail==========={}", data.getString("message"));
      return ReceiptVerifyBO.ofFail();
    }
    JSONObject transData = data.getJSONObject("data").getJSONObject("trans_data");
    if (payOk != transData.getInteger(payResult)) {
      log.debug("kuai kan receiptVerify fail==========={}", data.getString("message"));
      return ReceiptVerifyBO.ofFail();
    }
    // 4、返回结果
    String paymentType = transData.getString("pay_type");
    String currency = transData.getString("currency");
    String tradeNo = transData.getString("trans_id");
    return ReceiptVerifyBO.ofKuaiKan(true, paymentType, currency, tradeNo);
  }

  /**
   * 将MAP的参数进行签名
   *
   * @param map     参数集合
   * @param signKey 签名KEY
   * @return 签名字符串
   */
  public static String signKeyValue(Map<String, Object> map, String signKey, boolean sendBox) {
    map = DataUtils.sortMapByKey(map);
    StringBuilder str = new StringBuilder();
    if (map != null) {
      for (String key : map.keySet()) {
        if ("sign".equals(key)) {
          continue;
        }
        String value = Convert.toStr(map.get(key));
        if (StringUtils.isEmpty(value)) {
          continue;
        }
        str.append(key);
        str.append("=");
        str.append(value);
        str.append("&");
      }
    }
    str.append("key=");
    str.append(signKey);
    if (sendBox) {
      log.info("signKeyValue param=============={}", str.toString());
    }
    String sign = "";
    try {
      // 此处需要处理 NoSuchAlgorithmException
      MessageDigest messageDigest = MessageDigest.getInstance("MD5");
      // 计算 MD5 哈希值，
      byte[] b1 = messageDigest.digest(str.toString().getBytes(StandardCharsets.UTF_8));
      // 进行 Base64 编码获得签名
      sign = Base64.getEncoder().encodeToString(b1);
      if (sendBox) {
        log.info("signKeyValue sign=============={}", sign);
      }
    } catch (NoSuchAlgorithmException e) {
      log.error("signKeyValue NoSuchAlgorithmException==========", e);
    }
    return sign;
  }
}
